#include "MyString.h"
#include <iostream>
#include <cstring>
#include "MyString.h"

MyString::MyString()//无参构造
{
    std::cout<<"无参构造"<<std::endl;
    this->capacity = 10;
    this->size = 0;
    this->s = new char[this->capacity];
}

MyString::MyString(const char *str)//带参构造
{
    std::cout<<"带参构造"<<std::endl;
    this->size = strlen(str);//拷贝传入字符串的长度
    this->capacity = this->size + 1;//计算需使用的数组大小：字符串长度加一
    this->s = new char[this->capacity];//在当前创建相对应的数组大小空间，等待字符串的传入
    strcpy(this->s,str);//将传入的字符串拷贝到当前
}

MyString::~MyString()//析构
{
    std::cout<<"析构函数"<<std::endl;
    delete []this->s;
}

MyString::MyString(const MyString &str)//拷贝构造
{
    std::cout<<"拷贝构造"<<std::endl;
    this->capacity = str.capacity;//先拷贝数组大小
    this->size = str.size;//再拷贝数组长度
    this->s = new char[str.capacity];//再给数组创建新的空间
    strcpy(this->s,str.s);//将数组内容拷贝过来

}

MyString &MyString::operator=(const MyString &str)//运算符的重载,返回值是MyString则可以连续输出，不然返回值是void则不能
{
    std::cout<<"赋值运算符的重载"<<std::endl;
    delete []this->s;//运算符重载要先释放之前的空间
    this->capacity = str.capacity;//重复一遍拷贝构造的内容
    this->size = str.size;
    this->s = new char[str.capacity];
    strcpy(this->s,str.s);
    return *this;//因为最终要得到的数是*this拷贝src的字符串内容，所以输出*this
}

MyString &MyString::operator+=(const MyString &str)
{
    this->size += str.size;
    if(this->size >= this->capacity)
    {
        this->capacity = this->size + 1;
        char *newP = new char[this->capacity];
        strcpy(newP,this->s);
        delete []this->s;
        this->s = newP;
    }
    strcat(this->s,str.s);
    return *this;
}

void MyString::operator+=(const char &c)
{
    if(this->size >= this->capacity-1)//因为不能塞到最后一个位置，最后一个位置是\0
    {
        this->capacity *= 2;
        char *newP = new char[this->capacity];
        strcpy(newP,this->s);
        delete []this->s;
        this->s = newP;
    }
    this->s[this->size++] = c;
    this->s[this->size] = '\0';
}


MyString MyString::operator+(const MyString &str)
{
    MyString result(*this);//把我自己拷贝进来
    result += str;//加上传进来的字符串//此处为+=运算符重载
    return result;
}

MyString &MyString::operator-=(const MyString &str)
{
    std::cout<<"-=运算符的重载"<<std::endl;
    char *dest = strstr(this->s,str.s);//找到字字符串匹配的位置，定义为*dest
    while(dest != nullptr)//
    {
        char *back = dest + str.size;//找到字符匹配的末尾
        while(*back != '\0')//不遇到\0之前都一直加下去
        {
            *dest++ = *back++;//删除并不是真的删除，而是用后面的代码补上前面的
        }
        *dest = '\0';//在最末尾补充\0
        this->size -= str.size;//原字符串长度减去删除字符串的长度
        dest = strstr(this->s,str.s);//找下一个匹配的字符串
    }    
    return *this;//返回当前指针所指向的内容
    
}

MyString MyString::operator-(const MyString &str)
{
    MyString result(*this);
    result -= str;//此处为-=运算符重载
    return result;
}

char& MyString::operator[](int index)//定义数组中某下标的字符
{
    return this->s[index];
}

bool MyString::operator==(const MyString &str)
{
    return strcmp(this->s,str.s) == 0;//返回零则相等
}

bool MyString::operator!=(const MyString &str)
{
    return strcmp(this->s,str.s) != 0;//返回的不是零则不相等
}


std::ostream & operator<<(std::ostream &os, const MyString& str)
{
    os<<str.s;//我要输出的就是对象里指针指向的的内容
    return os;
}

std::istream & operator>>(std::istream &is, MyString& str)
{
    // char s[1024] = {0};//因为不知道输入多少字符，所以要先创建一个临时的并且足够大的空间，缓冲区最大为1024字节
    // is>>s;
    // str = s;
    char c = 0;
    while((c = getchar()) != '\n')
    {
        str +=c;//一个个的字符插入！！
    }
    return is;
}
